<?php

namespace app\common\utils;

/**
 * 系统相关信息
 */
class SystemInfo
{
    private string $system;
    private string $name;
    private string $host;
    private string $release;
    private string $version;
    private string $architecture;
    private array $memory = ['free' => 0, 'size' => 0];
    private array $disk = [];
    private string $phpVersion;

    public function __construct()
    {
        $this->system = PHP_OS_FAMILY;
        $this->name = php_uname('s');
        $this->host = php_uname('n');
        $this->release = php_uname('r');
        $this->version = php_uname('v');
        $this->architecture = php_uname('m');
        $this->phpVersion = phpversion();

        $isWin = str_contains(PHP_OS, 'WIN');
        if ($isWin) {
            exec('wmic os get FreePhysicalMemory,TotalVisibleMemorySize', $osInfo);

            $osInfo = array_values(array_filter(explode('  ', $osInfo[1])));
            $this->memory['free'] = sprintf('%.2f', $osInfo[0] / 1024 / 1024);
            $this->memory['size'] = round($osInfo[1] / 1024 / 1024);

            exec('wmic logicaldisk get Caption,FreeSpace,Size', $diskInfo);
            unset($diskInfo[0]);
            foreach ($diskInfo as $disk) {
                if (empty($disk)) {
                    continue;
                }
                $info = array_values(array_filter(explode('  ', $disk)));
                $this->disk[] = [
                    'caption' => $info[0],
                    'free' => sprintf('%.2f', $info[1] / 1024 / 1024 / 1024),
                    'size' => floor($info[2] / 1024 / 1024 / 1024),
                ];
            }
        } else {
            exec('df', $diskInfo);
            unset($diskInfo[0]);
            foreach ($diskInfo as $disk) {
                $info = array_values(array_filter(explode(' ', $disk)));
                if (!isset($info[5])) {
                    continue;
                }
                if (str_contains($info[0], 'tmp') || str_contains($info[5], 'docker')) {
                    continue;
                }
                $this->disk[] = [
                    'caption' => $info[5],
                    'free' => floor($info[2] / 1024 / 1024),
                    'size' => floor($info[1] / 1024 / 1024),
                ];
            }

            exec('free', $memoryInfo);
            $info = array_values(array_filter(explode(' ', $memoryInfo[1])));
            $this->memory['free'] = sprintf('%.2f', $info[3] / 1024 / 1024);
            $this->memory['size'] = round($info[1] / 1024 / 1024);
        }
    }

    /**
     * 系统
     * @return string
     */
    public function system(): string
    {
        return $this->system;
    }

    /**
     * 名称
     * @return string
     */
    public function name(): string
    {
        return $this->name;
    }

    /**
     * 主机名
     * @return string
     */
    public function host(): string
    {
        return $this->host;
    }

    /**
     * 发布号
     * @return string
     */
    public function release(): string
    {
        return $this->release;
    }

    /**
     * 版本
     * @return string
     */
    public function version(): string
    {
        return $this->version;
    }

    /**
     * 架构
     * @return string
     */
    public function architecture(): string
    {
        return $this->architecture;
    }

    /**
     * 内存
     * @return array
     */
    public function memory(): array
    {
        return $this->memory;
    }

    /**
     * 磁盘
     * @return array
     */
    public function disk(): array
    {
        return $this->disk;
    }

    /**
     * php版本
     * @return string
     */
    public function phpVersion(): string
    {
        return $this->phpVersion;
    }

    /**
     * nginx版本
     * @return string
     */
    public function nginxVersion(): string
    {
        exec('nginx -v', $nginxInfo, $nginxStatus);
        return (empty($nginxStatus) && !empty($nginxInfo)) ? $nginxInfo[0] : '-';
    }

    /**
     * mysql版本
     * @return string
     */
    public function mysqlVersion(): string
    {
        exec('mysql -V', $mysqlInfo, $mysqlStatus);
        return empty($mysqlStatus) ? explode(',', $mysqlInfo[0])[0] : '-';
    }

    /**
     * node版本
     * @return string
     */
    public function nodeVersion(): string
    {
        exec('node -v', $nodeInfo, $nodeStatus);
        return empty($nodeStatus) ? $nodeInfo[0] : '-';
    }

    /**
     * npm版本
     * @return string
     */
    public function npmVersion(): string
    {
        exec('npm -v', $npmInfo, $npmStatus);
        return empty($npmStatus) ? $npmInfo[0] : '-';
    }

    /**
     * 终端输出
     * @return void
     */
    public function terminal(): void
    {
        echo PHP_EOL;
        echo "系统:\t\t" . $this->system() . PHP_EOL;
        echo "名称:\t\t" . $this->name() . PHP_EOL;
        echo "主机名:\t\t" . $this->host() . PHP_EOL;
        echo "发布号:\t\t" . $this->release() . PHP_EOL;
        echo "版本:\t\t" . $this->version() . PHP_EOL;
        echo "架构:\t\t" . $this->architecture() . PHP_EOL;
        echo "内存:\t\t" . $this->memory()['size'] . 'G' . PHP_EOL;
        echo "内存剩余:\t" . $this->memory()['free'] . 'G (' .
            sprintf('%d', $this->memory()['free'] / $this->memory()['size'] * 100) . '%)' . PHP_EOL;

        foreach ($this->disk() as $disk) {
            echo "磁盘容量:" . $disk['size'] . "G\t剩余:" . $disk['free'] . 'G (' .
                sprintf('%0d', $disk['free'] / $disk['size'] * 100) . "%)\t" . $disk['caption'] . PHP_EOL;
        }

        echo PHP_EOL;
        echo "nginx版本:\t" . $this->nginxVersion() . PHP_EOL;
        echo "php版本:\t" . $this->phpVersion() . PHP_EOL;
        echo "mysql版本:\t" . $this->mysqlVersion() . PHP_EOL;
        echo "node版本:\t" . $this->nodeVersion() . PHP_EOL;
        echo "npm版本:\t" . $this->npmVersion() . PHP_EOL;

        echo PHP_EOL;
    }
}